package webclient

import (
	"fmt"
	"gitee.com/ichub/webcli/common/base/baseconfig"
	"gitee.com/ichub/webcli/common/base/basedto"
	"gitee.com/ichub/webcli/common/base/baseutils/jsonutils"
	"gitee.com/ichub/webcli/common/base/baseutils/stringutils"
	"gitee.com/ichub/webcli/common/ichubconfig"
	"gitee.com/ichub/webcli/common/ichublog"
	"github.com/imroc/req"
	"github.com/micro/go-micro/v2/client/selector"
	"github.com/micro/go-micro/v2/registry"
	"github.com/micro/go-micro/v2/registry/etcd"
	"github.com/sirupsen/logrus"
	"github.com/stretchr/testify/suite"
	"strings"
	"time"
)

/*
@Title    文件名称: ichub_webclient.go
@Description  描述:  WEB客户端服务发现，支持多个服务

@Author  作者: leijianming@163.com  时间(2024-02-18 22:38:21)
@Update  作者: leijianming@163.com  时间(2024-02-18 22:38:21)
*/

const web_timeout = 20 * time.Second

type IchubWebClient struct {
	//服务名称
	ServerName string
	// 可测试性 baseurl -> http://xxx.xxx.xxx.xxx:xx
	TestUrl, BaseUrl string

	// etcd注册服务器地址  xxx.xxx.xxx.xxx:xx
	EtcdHost string
	Registry registry.Registry `json:"-"`
}

func (client *IchubWebClient) String() string {
	return jsonutils.ToJsonPretty(client)
}

func NewIchubWebClient() *IchubWebClient {
	client := &IchubWebClient{}
	client.ReadCfg()
	client.Register()
	return client
}
func NewWebClient(clientDto *baseconfig.WebClientDto) *IchubWebClient {
	client := &IchubWebClient{}
	client.ValueOf(clientDto)
	client.Register()
	return client
}

func (client *IchubWebClient) Init() *IchubWebClient {
	client.ReadCfg()

	//新建一个注册的地址，也就是我们服务启动的机器ip+端口
	client.Register()
	return client
}
func (client *IchubWebClient) Register() *IchubWebClient {

	//新建一个注册的地址，也就是我们服务启动的机器ip+端口
	client.Registry = etcd.NewRegistry(
		registry.Addrs(client.EtcdHost),
	)
	return client
}
func (client *IchubWebClient) SetBaseUrl(baseUrl string) string {
	if client.TestUrl != "" {
		baseUrl = client.TestUrl
	}

	if !strings.Contains(baseUrl, "http://") {
		baseUrl = "http://" + baseUrl
	}

	client.BaseUrl = baseUrl
	return baseUrl
}
func (client *IchubWebClient) ValueOf(clientDto *baseconfig.WebClientDto) {

	client.ServerName = clientDto.ServerName
	client.TestUrl = clientDto.TestUrl
	client.EtcdHost = clientDto.EtcdHost
}

func (client *IchubWebClient) ReadCfg() {
	var config = ichubconfig.NewConfig()
	clientDto := config.ReadIchubWebClient()
	client.ValueOf(clientDto)

}

func (client *IchubWebClient) GetServiceAddrs() []*registry.Service {
	servers, err := client.Registry.GetService(client.ServerName)
	if err != nil {
		fmt.Println(err)
	}
	return servers
}
func (client *IchubWebClient) GetServiceAddr() (address string) {
	return client.GetServiceAddrBy(client.ServerName)
}

func (client *IchubWebClient) RefreshAddr() {

	client.BaseUrl = client.GetServiceAddr()
	client.SetBaseUrl(client.BaseUrl)
}

func (client *IchubWebClient) GetServiceAddrBy(ServerName string) (address string) {
	var retryTimes int
	for {
		servers, err := client.Registry.GetService(ServerName)
		logrus.Info(servers)
		if err != nil {
			logrus.Error(err.Error())
		}
		var services []*registry.Service
		for _, value := range servers {
			logrus.Debug(value.Name, ":", value.Version)
			services = append(services, value)
		}
		// 获取其中一个服务的信息
		next := selector.RoundRobin(services)
		if node, err := next(); err == nil {
			address = node.Address
		}
		if len(address) > 0 {
			return
		}

		// 重试次数++
		retryTimes++
		time.Sleep(1 * time.Second)
		// 重试5次 返回空
		if retryTimes >= 5 {
			return
		}
	}
}
func (client *IchubWebClient) Get(url string) *basedto.IchubResult {
	//cli := req.New().SetTimeout(web_timeout)
	resp, err := req.New().Get(url)

	var result = client.Resp2IchubResult(resp, err)
	//cli.SetCloseConnection(true)
	return result
}

func (client *IchubWebClient) Post(body, url string) *basedto.IchubResult {

	//cli := resty.New().SetTimeout(web_timeout)
	resp, err := req.New().Post(url, body)
	var result = client.Resp2IchubResult(resp, err)
	//cli.SetCloseConnection(true)
	return result
}

func (client *IchubWebClient) PostBatch(body, url string) *basedto.IchubResults {

	//cli := resty.New().SetTimeout(web_timeout)
	resp, err := req.New().Post(url, body)

	results := client.Resp2IchubResults(resp, err)
	//cli.SetCloseConnection(true)
	return results
}

func (client *IchubWebClient) Resp2IchubResult(resp *req.Resp, err error) *basedto.IchubResult {

	var ichubResult = basedto.NewIchubResult()
	if err != nil {
		ichubResult.CodeMsg(500, err.Error())

	} else if resp.Response().StatusCode != 200 {
		ichubResult.CodeMsg(resp.Response().StatusCode, string(resp.Bytes()))
	} else {
		ichubResult, err = basedto.NewIchubResult().FromJson(resp.Bytes())

		if err != nil {
			ichubResult.CodeMsg(500, string(resp.Bytes()))
		}
	}
	return ichubResult

}

func (client *IchubWebClient) Resp2IchubResults(resp *req.Resp, err error) *basedto.IchubResults {

	var results *basedto.IchubResults = basedto.NewIchubResults()

	if err != nil {
		results.FailCode(500, err.Error())

	} else if resp.Response().StatusCode != 200 {
		results.CodeMsg(resp.Response().StatusCode, string(resp.Bytes()))

	} else {
		_, err := results.FromJson(resp.Bytes())
		if err != nil {
			results.CodeMsg(500, string(resp.Bytes()))
		}
	}
	for _, v := range results.Data {
		v.InitProxy(v)
	}
	return results

}
func (client *IchubWebClient) Check(suite suite.Suite, ichubResult *basedto.IchubResult, key string, exp interface{}) {

	var value = ichubResult.ValueByKey(key)
	ichublog.IchubLog.Println("\r\nichubResult=", ichubResult.ToString())
	ev := stringutils.ToStringWith(exp)
	rv := stringutils.ToStringWith(value)
	suite.Equal(ev, rv, "ev == rv  "+ev+","+rv)

}
